﻿/******************************************************************************
 * Name         : EchoLogger.cpp
 * Author       : 671643387
 * Date         : 2015年9月8日
 * Description  :
 *****************************************************************************/

#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#if defined(__WINDOWS__)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif
#include <dev/base/Thread.hpp>
#include <dev/base/TimeUtil.hpp>
#include "Logger.hpp"
using namespace sxr::common;

#if defined(__LINUX__)
#define RESET   "\033[0m"
#define BLACK   "\033[30m"      /* Black */
#define RED     "\033[31m"      /* Red */
#define GREEN   "\033[32m"      /* Green */
#define YELLOW  "\033[33m"      /* Yellow */
#define BLUE    "\033[34m"      /* Blue */
#define MAGENTA "\033[35m"      /* Magenta */
#define CYAN    "\033[36m"      /* Cyan */
#define WHITE   "\033[37m"      /* White */
#define BOLDBLACK   "\033[1m\033[30m"      /* Bold Black */
#define BOLDRED     "\033[1m\033[31m"      /* Bold Red */
#define BOLDGREEN   "\033[1m\033[32m"      /* Bold Green */
#define BOLDYELLOW  "\033[1m\033[33m"      /* Bold Yellow */
#define BOLDBLUE    "\033[1m\033[34m"      /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m"      /* Bold Magenta */
#define BOLDCYAN    "\033[1m\033[36m"      /* Bold Cyan */
#define BOLDWHITE   "\033[1m\033[37m"      /* Bold White */

#define LOG_CONSOLE_COLOR_FOREGROUND_BLUE	BLUE
#define LOG_CONSOLE_COLOR_FOREGROUND_GREEN	GREEN
#define LOG_CONSOLE_COLOR_FOREGROUND_RED	RED
#define LOG_CONSOLE_COLOR_FOREGROUND_YELLOW	YELLOW
#define LOG_CONSOLE_COLOR_FOREGROUND_WHITE	WHITE

void set_console_color(const char* forecolor = LOG_CONSOLE_COLOR_FOREGROUND_WHITE)
{
	std::cout << forecolor;
}
#elif defined(__WINDOWS__)
#define LOG_CONSOLE_COLOR_FOREGROUND_BLUE	FOREGROUND_BLUE
#define LOG_CONSOLE_COLOR_FOREGROUND_GREEN	FOREGROUND_GREEN
#define LOG_CONSOLE_COLOR_FOREGROUND_RED	FOREGROUND_RED
#define LOG_CONSOLE_COLOR_FOREGROUND_YELLOW	FOREGROUND_RED | FOREGROUND_GREEN
#define LOG_CONSOLE_COLOR_FOREGROUND_WHITE	FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE

void set_console_color(unsigned short forecolor = LOG_CONSOLE_COLOR_FOREGROUND_WHITE)
{
	HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); //获取缓冲区句柄
	SetConsoleTextAttribute(hCon, forecolor | 0); //设置文本及背景色
}
#endif

// 日志记录器
static const dev::base::LoggerPtr scLogger(new sxr::common::Logger());
dev::base::LoggerPtr sxr::common::getLogger(void)
{
    return scLogger;
}

void print_vargs(const char* format, va_list arg)
{
    char buff[0x1000] = {0};
    vsnprintf(buff, sizeof(buff), format, arg);
	std::cout << dev::base::TimeUtil::fromStartup()
		<< "," << dev::base::Thread::currentTid() << ",";

	char* first = &buff[0];
	char* end = &buff[0x1000];
	char *find = std::find(first, end, '[');
	if (find != end)
	{
		*find = '\0';
		std::cout << first;

		*find = '[';
		first = find;
		find = std::find(first, end, ']');
		if (find != end)
		{
			if ((strncmp(first, "[OK]", 4) == 0) && ((find - first) >= 3))
			{
				set_console_color(LOG_CONSOLE_COLOR_FOREGROUND_GREEN);
				std::cout << "[OK]";
				first = find + 1;
				set_console_color(LOG_CONSOLE_COLOR_FOREGROUND_WHITE);
			}
			else if ((strncmp(first, "[FAIL]", 6) == 0) && ((find - first) >= 5))
			{
				set_console_color(LOG_CONSOLE_COLOR_FOREGROUND_RED);
				std::cout << "[FAIL]";
				first = find + 1;
				set_console_color(LOG_CONSOLE_COLOR_FOREGROUND_WHITE);
			}
			else 
			{
				set_console_color(LOG_CONSOLE_COLOR_FOREGROUND_YELLOW);
			}
		}
		else
		{
			set_console_color(LOG_CONSOLE_COLOR_FOREGROUND_YELLOW);
		}
	}

	std::cout << first << std::endl;
	set_console_color(LOG_CONSOLE_COLOR_FOREGROUND_WHITE);
}

Logger::Logger()
{

}

Logger::~Logger()
{

}

void Logger::log(const char* format, ...)
{
    
    va_list arg;
    va_start(arg, format);
    print_vargs(format, arg);
    va_end(arg);
}

void Logger::warning(const char* format, ...)
{
    va_list arg;
    va_start(arg, format);
    print_vargs(format, arg);
    va_end(arg);
}

void Logger::error(const char* format, ...)
{
    va_list arg;
    va_start(arg, format);
    print_vargs(format, arg);
    va_end(arg);
}
